package com.ruoyi.common.core.plugin;

import com.ruoyi.common.core.context.SecurityContextHolder;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;

import java.lang.reflect.Field;
import java.sql.PreparedStatement;
import java.util.Map;
import java.util.Properties;

@Intercepts({@Signature(type = ParameterHandler.class, method = "setParameters", args = {PreparedStatement.class})})
public class SecurityContextPlugin implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        ParameterHandler parameterHandler = (ParameterHandler) invocation.getTarget();
        MetaObject metaObject = SystemMetaObject.forObject(parameterHandler);
        Object parameterObject = parameterHandler.getParameterObject();

        String enterpriseCode = SecurityContextHolder.getEnterpriseCode();
        if (enterpriseCode != null && !enterpriseCode.isEmpty()) {
            if (parameterObject instanceof Map) {
                @SuppressWarnings("unchecked")
                Map<String, Object> parameterMap = (Map<String, Object>) parameterObject;
                if (!parameterMap.containsKey("enterpriseCode")) {
                    parameterMap.put("enterpriseCode", enterpriseCode);
                }
            } else {
                if (getFieldValue(parameterObject, "enterpriseCode") == null) {
                    setField(parameterObject, "enterpriseCode", enterpriseCode);
                }
            }
        }

        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
    }

    /**
     * 使用反射设置字段值
     *
     * @param obj       对象实例
     * @param fieldName 字段名
     * @param value     字段值
     */
    private void setField(Object obj, String fieldName, Object value) {
        try {
            Field field = obj.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            field.set(obj, value);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            // 处理异常，例如日志记录
            e.printStackTrace();
        }
    }

    /**
     * 使用反射获取字段值
     *
     * @param obj       对象实例
     * @param fieldName 字段名
     * @return 字段值
     */
    private Object getFieldValue(Object obj, String fieldName) {
        try {
            Field field = obj.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            return field.get(obj);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            // 处理异常，例如日志记录
            e.printStackTrace();
            return null;
        }
    }
}
